<template>
  <div class="container">
    <h3>vue+openlayers: 定位动画（平移-弹性平移-飞行）</h3>
    <h4>
      <el-button type="primary" size="mini" @click="pan">平移</el-button>
      <el-button type="primary" size="mini" @click="elastic">弹性平移</el-button>
      <el-button type="primary" size="mini" @click="fly">飞行</el-button>
    </h4>
    <div id="vue-openlayers"></div>
  </div>
</template>

<script>
import 'ol/ol.css';
import { Map, View } from 'ol';
import Tile from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import * as olEasing from 'ol/easing'; // 缓动函数
export default {
  data() {
    return {
      map: null
    }
  },
  mounted() {
    this.initMap();
  },
  methods: {
    pan() {
      this.map.getView().animate({
        center: [119, 39],
        duration: 2000, // 动画持续时间
      })
    },
    elastic() {
      this.map.getView().animate({
        center: [-36, -22],
        easing: olEasing.elastic // 弹性平移
      })
    },
    fly() {
      this.flyTo([119, 39]) // 飞行到指定位置
    },
    flyTo(location, done = () => {}) { // 参数是 飞行到的位置 和 飞行结束后的回调函数
      let view = this.map.getView()
      let duration = 2000 // 动画持续时间
      let zoom = view.getZoom() // 当前缩放级别
      let parts = 2 // 动画分为两部分
      let called = false // 飞行是否结束
      function callback(complete) {
        --parts;
        if (called) {
          return
        }
        if (parts === 0 || !complete) {
          called = true
          done(complete)
        }
      }
      view.animate({
        zoom: zoom - 1, // 缩放级别减1
        duration: duration / 2 // 动画持续时间的一半
      },{
        zoom: zoom, // 缩放级别
        duration: duration / 2 // 动画持续时间的一半
      }, callback)
    },

    initMap() {
      let layer = new Tile({
        source: new XYZ({
          url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7'
        })
      })
      this.map = new Map({
        target: 'vue-openlayers',
        layers: [layer],
        view: new View({
          center: [116.397411, 39.909186],
          zoom: 7,
          projection: 'EPSG:4326'
        }),
        loadTilesWhileAnimating: true // 动画时加载瓦片
      })
    }
  }
}
</script>

<style scoped>
    .container {
        width: 100%;
        height: 750px;
        margin: 50px auto;
        border: 1px solid #42B983;
    }

    #vue-openlayers {
        width: 100%;
        height: 720px;
        margin: 0 auto;
        border: 1px solid #42B983;
        position: relative;
    }

</style>
